package com.example.cron.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.common.entity.OnlineConsultation;
import com.example.common.entity.OrderMain;
import com.example.common.enums.OCStatus;
import com.example.common.enums.SystemStatus;
import com.example.common.sendhttp.HxSendHttp;
import com.example.common.support.ApiException;
import com.example.common.support.Result;
import com.example.common.utils.IdUtils;
import com.example.common.utils.RedisUtils;
import com.example.cron.feign.FileFeignService;
import com.example.cron.jpa.OnlineConsultationRepository;
import com.example.cron.jpa.OrderMainRepository;
import com.example.cron.mapper.ConsultationMapper;
import com.example.cron.service.InquireTask;
import com.example.cron.properties.WxProp;
import com.example.cron.utils.WxPayUtils;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;

/**
 * @ClassName InquireTaskImpl
 * @Author wengjt
 * @Date 2021/3/239:45
 * @Description 问诊相关定时任务
 **/
@Component
@Slf4j
public class InquireTaskImpl implements InquireTask {
    @Value("${hx.parameter.grantType}")
    private String grantType;

    @Value("${hx.parameter.clientId}")
    private String clientId;

    @Value("${hx.parameter.clientSecret}")
    private String clientSecret;

    @Value("${system.downPath}")
    private String downPath;

    @Resource
    private OrderMainRepository orderMainRepository;

    @Resource
    private OnlineConsultationRepository onlineConsultationRepository;


    @Resource
    private ConsultationMapper consultationMapper;

    @Resource
    private WxProp wxProp;

    @Resource
    private HxSendHttp hxSendHttp;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private FileFeignService fileFeignService;


    /**
     * @return
     * @Author wengjt
     * @Description 问诊未接诊超时处理//TODO
     * @Date 9:54 2021/3/23
     * @Param
     **/
    @Override
    public void cancelTimeOutInquireOrder() {
        orderMainRepository.findBySystemStatusAndOcStatusAndOrderPayTimeNotNull(SystemStatus.PAY.getName().longValue(), OCStatus.NoReceiv.getName()).stream().filter(orderMain -> {
            //挑选出已经过期的订单;
            Date date = new Date();
            long now = date.getTime();
            long end = orderMain.getOrderPayTime().getTime() + orderMain.getToBeReceive() * 60 * 1000;
            return now > end;
        }).forEach(new Consumer<OrderMain>() {
            @Override
            @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
            public void accept(OrderMain orderMain) {
                orderMain.setSystemStatus(SystemStatus.CANCEL.getName().longValue());
                orderMain.setOcStatus(OCStatus.TimeOut.getName());

                //修改在线会话状态
                OnlineConsultation onlineConsultation = onlineConsultationRepository.findByOrderNo(orderMain.getOrderNo());
                onlineConsultation.setOcStatus(OCStatus.TimeOut.getName());
                onlineConsultation.setFactFinishTime(new Date());
                WxPayService wxPayService = new WxPayServiceImpl();
                WxPayConfig wxPayConfig = new WxPayConfig();
                wxPayConfig.setAppId(wxProp.getWxAppletsAppId());
                wxPayConfig.setMchId(wxProp.getMchId());
                wxPayConfig.setMchKey(wxProp.getMchKey());
                wxPayConfig.setKeyPath(wxProp.getKeyPath());
                wxPayService.setConfig(wxPayConfig);
                WxPayRefundRequest request = new WxPayRefundRequest();
                request.setTransactionId(orderMain.getTransactionID());
                request.setOutRefundNo("R" + IdUtils.generateId());
                request.setTotalFee(orderMain.getAskMoney().multiply(new BigDecimal("100")).intValue());
                request.setRefundFee(orderMain.getAskMoney().multiply(new BigDecimal("100")).intValue());
/*                //退款操作
                try {
                    wxPayService.refund(request);
                } catch (WxPayException e) {
                    log.error(e.getMessage());
                    throw new ApiException(1, e.getMessage());
                }*/
                onlineConsultationRepository.save(onlineConsultation);
                orderMainRepository.save(orderMain);
            }
        });
    }

    @Override
    public void cancelTimeOutSessionOrder() {
        orderMainRepository.findBySystemStatusAndOcStatusAndOrderPayTimeNotNull(SystemStatus.PAY.getName().longValue(), OCStatus.Receiv.getName()).stream().filter(orderMain -> {
            //删选出已经超时的问诊订单
            Date date = new Date();
            long now = date.getTime();
            long end = orderMain.getReceiveTime().getTime() + orderMain.getReceive() * 60 * 1000;
            return now > end;
        }).forEach(new Consumer<OrderMain>() {
            @Override
            @Transactional(rollbackFor = Exception.class, transactionManager = "jpaTransactionManager")
            public void accept(OrderMain orderMain) {
                //修改会诊订单状态
                orderMain.setOcStatus(OCStatus.Completed.getName());
                //修改在线会话状态
                OnlineConsultation onlineConsultation = onlineConsultationRepository.findByOrderNo(orderMain.getOrderNo());
                onlineConsultation.setOcStatus(OCStatus.Completed.getName());
                onlineConsultation.setFactFinishTime(new Date());
                onlineConsultationRepository.save(onlineConsultation);
                orderMainRepository.save(orderMain);
            }
        });
    }

    /**
     * 下载音频文件
     */
    @Override
    public void downLoadAudiovideo() {
        if (redisUtils.hasKey(clientId + "-Hx")) {
            String token = (String) redisUtils.get(clientId + "-Hx");
            getImContentList(token);
        } else {
            JSONObject token = hxSendHttp.getToken(grantType, clientId, clientSecret);
            String accessToken = (String) token.get("access_token");
            Integer expiresIn = (Integer) token.get("expires_in");
            boolean set = redisUtils.set(clientId + "-Hx", "Bearer " + accessToken, Long.valueOf(expiresIn));
            if (set) {
                getImContentList(accessToken);

            }
        }
    }


    /**
     * 文件上傳到服務器
     *
     * @param token
     */
    private void getImContentList(String token) {
        List<String> result = consultationMapper.getImContentList();
        // list 转为 array list
        List<String> list = new ArrayList<>(result);

        for (int i = 0; i < list.size(); i++) {
            // 发送获得url 的请求
            List<String> urlList = new ArrayList<>(hxSendHttp.getVideoList(token, list.get(i)));

            for (int j = 0; j < urlList.size(); j++) {
                // 下载文件
                HttpUtil.downloadFile(urlList.get(j), FileUtil.file(downPath));

                // 获得原文件名
                String fileName = getFileName(urlList.get(j));
                try {
                    File file = new File(downPath + fileName);
                    FileInputStream inputStream = new FileInputStream(file);
                    String name = list.get(i) + "(" + j + ")" + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
                    // 将file 转为multipartFile
                    MockMultipartFile mockMultipartFile = new MockMultipartFile(name, name, ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
                    // 远程调用上传
                    Result<Object> upload = fileFeignService.upload(mockMultipartFile);
                    if ("操作成功".equals(upload.getMsg())) {
                        // 删除文件
                        deleteFile(downPath + fileName);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 修改数据库
            consultationMapper.updateIsDown(list.get(i));
        }
    }


    /**
     * 获得文件的名称
     *
     * @param url 下载文件的url
     * @return 文件的名称
     */
    private String getFileName(String url) {
        String[] split = url.split("/");
        String last = split[split.length - 1];
        return last.substring(0, last.indexOf("?"));
    }

    /**
     * 文件删除
     *
     * @param fileName 删除的文件名
     * @return 是否删除
     */
    public boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功！");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败！");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败：" + fileName + "不存在！");
            return false;
        }
    }


}
